package com.mrx.bot.telegram.utils;

import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.stream.Stream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * @author Mr.X
 * @since 2025/6/14 08:49
 */
public class ZipUtils {

    public static void zip(File src, File dst) throws IOException {
        zip(src.getAbsolutePath(), dst.getAbsolutePath());
    }

    /**
     * 递归压缩文件或目录到指定的ZIP文件
     *
     * @param src 要压缩的源文件或目录路径
     * @param dst 压缩后的ZIP文件路径
     * @throws IOException 如果发生I/O错误
     */
    public static void zip(String src, String dst) throws IOException {
        Path sourcePath = Paths.get(src);
        Path destinationPath = Paths.get(dst);
        try (ZipOutputStream zipOutputStream = new ZipOutputStream(new FileOutputStream(destinationPath.toFile()))) {
            if (Files.isDirectory(sourcePath)) {
                // 如果是目录，递归处理
                zipDirectory(sourcePath, sourcePath, zipOutputStream);
            } else {
                // 如果是文件，直接添加到ZIP
                addToZip(sourcePath.getParent(), sourcePath, zipOutputStream);
            }
        }
    }

    /**
     * 递归压缩目录
     *
     * @param rootDir         根目录
     * @param currentDir      当前处理的目录
     * @param zipOutputStream ZIP输出流
     * @throws IOException 如果发生I/O错误
     */
    private static void zipDirectory(Path rootDir, Path currentDir, ZipOutputStream zipOutputStream) throws IOException {
        try (Stream<Path> pathStream = Files.list(currentDir)) {
            pathStream.forEach(file -> {
                try {
                    if (Files.isDirectory(file)) {
                        // 如果是子目录，递归处理
                        zipDirectory(rootDir, file, zipOutputStream);
                    } else {
                        // 如果是文件，添加到ZIP
                        addToZip(rootDir, file, zipOutputStream);
                    }
                } catch (IOException e) {
                    throw new UncheckedIOException(e);
                }
            });
        }
    }

    /**
     * 将文件添加到ZIP输出流
     *
     * @param rootDir         根目录
     * @param file            要添加的文件
     * @param zipOutputStream ZIP输出流
     * @throws IOException 如果发生I/O错误
     */
    private static void addToZip(Path rootDir, Path file, ZipOutputStream zipOutputStream) throws IOException {
        Path entryPath = rootDir.relativize(file);
        ZipEntry zipEntry = new ZipEntry(entryPath.toString());
        zipOutputStream.putNextEntry(zipEntry);

        try (InputStream inputStream = Files.newInputStream(file)) {
            byte[] buffer = new byte[1024];
            int length;
            while ((length = inputStream.read(buffer)) > 0) {
                zipOutputStream.write(buffer, 0, length);
            }
        }

        zipOutputStream.closeEntry();
    }

}